﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;

public class ModelEventTab
{
    Vector2 scrollPos;
    Editor editor;
    float time;
    int selectIndex = 0;
    int selectEventIndex = -1;
    Editor window;
    AnimationClipEvent data;
    FieldInfo timeControl;
    FieldInfo m_AvatarPreview;
    PropertyInfo normalizedTime;
    Dictionary<Type, BaseDrawType> drawTypes = new Dictionary<Type, BaseDrawType>();
    public ModelEventTab(Editor window, AnimationClipEvent data)
    {
        this.window = window;
        this.data = data;

        foreach (var type in this.GetType().Assembly.GetTypes())
        {
            if (type.BaseType == typeof(BaseDrawType))
            {
                var instance = Activator.CreateInstance(type) as BaseDrawType;
                drawTypes.Add(instance.type, instance);
            }
        }

        UpdateSelect(selectIndex);

    }

    public  void OnPreviewSettings()
    {
        if (editor != null)
        {
            editor.OnPreviewSettings();
            time = (float)normalizedTime.GetValue(timeControl.GetValue(m_AvatarPreview.GetValue(editor)));
        }
    }

    public  void OnInteractivePreviewGUI(Rect r, GUIStyle background)
    {
        if (editor != null)
        {
            editor.OnInteractivePreviewGUI(r, background);
        }
    }

    public  bool HasPreviewGUI()
    {
        return this.editor != null && this.editor.HasPreviewGUI();
    }

    public void Draw()
    {
        scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
        {
            DrawState();
            DrawClipEvent();
        }
        EditorGUILayout.EndScrollView();

        EditorGUILayout.BeginHorizontal();
        {
            if (GUILayout.Button("添加事件", GUILayout.MinHeight(50)))
            {
                if (data.clips.Count == 0 || data.clips[selectIndex].value == null)
                    return;

                var ed = new AnimationEventData { clipName = data.clips[selectIndex].kay.name, time = time, eventIndex = 0 };
                UpdateFunctionName(ed, 0);
                data.eventDatas.Add(ed);
            }
            if (GUILayout.Button("清空事件", GUILayout.MinHeight(50)))
            {
                var item = data.clips[selectIndex];
                var list = data.eventDatas.Where(x => x.clipName == item.kay.name).ToList();
                foreach(var tmp in list)
                {
                    data.eventDatas.Remove(tmp);
                }
            }
        }
        EditorGUILayout.EndHorizontal();
    }

    void DrawState()
    {
        EditorGUILayout.BeginVertical("Box");
        {
            EditorGUILayout.BeginHorizontal();
            {
                EditorGUILayout.LabelField("替换状态机动画");
                if (GUILayout.Button("清空动画"))
                {
                    for (int i = 0; i < data.clips.Count; i++)
                    {
                        data.clips[i].value = null;
                    }
                }
            }

            EditorGUILayout.EndHorizontal();

            DrawLine();

            for (int i = 0; i < data.clips.Count; i++)
            {
                var key = data.clips[i].kay;
                var rect = EditorGUILayout.GetControlRect();

                if (selectIndex == i)
                {
                    EditorGUI.DrawRect(rect, Color.gray);
                }

                EditorGUI.BeginChangeCheck();
                var value = EditorGUI.ObjectField(rect, new GUIContent(key.name), data.clips[i].value, typeof(AnimationClip), false) as AnimationClip;
                if (EditorGUI.EndChangeCheck())
                {
                    data.clips[i].value = value;
                    UpdatePreview();
                }

                if (rect.MouseDown())
                {
                    UpdateSelect(i);
                    Event.current.Use();
                    window.Repaint();
                }
            }
        }
        EditorGUILayout.EndVertical();
    }

    void DrawClipEvent()
    {
        if (data.clips.Count <= 0)
            return;

        var item = data.clips[selectIndex];

        var list = data.eventDatas.Where(x => x.clipName == item.kay.name).ToList();
        //list.Sort((a, b) => a.time.CompareTo(b.time));
        for (int i = 0; i < list.Count; i++)
        {
            var _event = list[i];
            _event.eventIndex = i;
            var rect = EditorGUILayout.BeginHorizontal("Box");
            {
                if (selectEventIndex == _event.GetHashCode())
                {
                    EditorGUI.DrawRect(rect, Color.gray);
                }
                EditorGUILayout.BeginVertical();
                {
                  //  EditorGUILayout.LabelField("index", _event.eventIndex.ToString());
                    EditorGUILayout.BeginHorizontal();
                    {
                        EditorGUI.BeginChangeCheck();
                        _event.time = EditorGUILayout.Slider("触发时间", _event.time,0,1f);
                        
                        if (GUILayout.Button("更新时间", GUILayout.MaxWidth(60)))
                        {
                            _event.time = time;
                        }
                    }
                    EditorGUILayout.EndHorizontal();
                    EditorGUI.BeginChangeCheck();
                    _event.index = EditorGUILayout.Popup("调用方法", _event.index, data.functions.ToArray());
                    if (EditorGUI.EndChangeCheck())
                    {
                        UpdateFunctionName(_event, _event.index);
                      
                    }

                    if(_event.index>= this.data.functions.Count)
                    {
                        UpdateFunctionName(_event, 0);
                    }

                    if(this.data.functionEditors.ContainsKey(_event.functionName))
                    {
                        var types = this.data.functionEditors[_event.functionName];
                        var names = this.data.paramterEditors[_event.functionName];
                        for (int j = 0; j < types.Length; j++)
                        {
                            if (types[j].FullName != _event.types[j])
                            {
                                _event.types[j] = types[j].FullName;
                                _event.parameters[j] = string.Empty;
                            }
                            if (drawTypes.ContainsKey(types[j]))
                            {
                                _event.parameters[j] = drawTypes[types[j]].Draw(j < names.Length ? names[j] : types[j].Name, _event.parameters[j]);
                            }
                        }
                    }
                }
                EditorGUILayout.EndVertical();

                if (GUILayout.Button("删除事件", GUILayout.MinHeight(52)))
                {
                    data.eventDatas.Remove(_event);
                    window.Repaint();
                    return;
                }
            }
            EditorGUILayout.EndHorizontal();
            if (rect.MouseDown())
            {
                selectEventIndex = _event.GetHashCode();
                window.Repaint();

            }
        }
    }

    void DrawLine(int height = 5)
    {
        var rect = EditorGUILayout.GetControlRect(GUILayout.MaxHeight(height));
        rect.y += height / 2;
        rect.height = 2;
        EditorGUI.DrawRect(rect, Color.gray);

    }

    public void UpdateSelect(int index)
    {
        if (data.clips.Count == 0)
            return;
        selectIndex = index;

        UpdatePreview();
    }

    void UpdatePreview()
    {
        if (data.clips[selectIndex].value == null)
            return;

        editor = Editor.CreateEditor(data.clips[selectIndex].value, Assembly.GetAssembly(typeof(Editor)).GetType("UnityEditor.AnimationClipEditor", true));
        if (editor != null)
        {
            m_AvatarPreview = editor.GetType().GetField("m_AvatarPreview", BindingFlags.Instance | BindingFlags.NonPublic);
            timeControl = m_AvatarPreview.FieldType.GetField("timeControl", BindingFlags.Instance | BindingFlags.Public);
            normalizedTime = timeControl.FieldType.GetProperty("normalizedTime", BindingFlags.Instance | BindingFlags.Public);
        }
    }

    void UpdateFunctionName(AnimationEventData data, int index)
    {
        data.index = index;
        data.functionName = this.data.functions[data.index];
        var array = this.data.functionEditors[data.functionName];
        data.parameters = new string[array.Length];
        data.types = new string[array.Length];
        for (var j = 0; j < array.Length; j++)
        {
            data.types[j] = array[j].FullName;
        }
    }
}
